查看原文
其他

如何创建一个自动改变的 favicon

朱宁 大前端技术之路 2022-06-29

(给大前端技术之路加星标,提升前端技能

前几天我发现了一个免费又好用的Favicon制作工具,与其他Favicon生成器不同的是,它可以让你用一个字符或emoji从零开始创建Favicon。我很好奇地看过它的代码后,就有了一些不同角度的思考。

结合之前阅读的材料,让我觉得更改网站Favicon是可以做到的。实际上已经有一些网站通过这种动态更新的方式给用户发送通知:当图标变为红点或者其他指示性东西的时候,表示页面上正在发生或已经发生的变化。

刚开始我在 emojipedia.org 这个网站里来获取灵感,这时候突然有这样的一个想法:为什么不用时钟图标(🕛)和其他相关的图标来显示时间呢?每分钟检查一次,然后用对应的图标去表示当前的时间。

在这篇文章中我们就会用 JavaScript 来实现这一功能。因为我经常使用 Gatsby(一款基于React构建的静态站点生成器),所以我们也会在 React 中去做演示。其实不管你要用Favicon做什么,怎么做,这些想法都是有利于你之后去解决问题的。

下面这个函数,就是以 emoji 作为参数,返回一个有效的图像或(图标)的data url:

// Thanks to https://formito.com/tools/favicon

const faviconHref = emoji =>
  `data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 width=%22256%22 height=%22256%22 viewBox=%220 0 100 100%22><text x=%2250%%22 y=%2250%%22 dominant-baseline=%22central%22 text-anchor=%22middle%22 font-size=%2280%22>${emoji}</text></svg>`

这个函数,针对<head>中的<link>标签加载图标,js 改变<link>标签中herf值实现改变 emoji 的功能:

const changeFavicon = emoji => {
  // Ensure we have access to the document, i.e. we are in the browser.
  if (typeof window === 'undefined'return

  const link =
    window.document.querySelector("link[rel*='icon']") ||
    window.document.createElement("link")
  link.type = "image/svg+xml"
  link.rel = "shortcut icon"
  link.href = faviconHref(emoji)

  window.document.getElementsByTagName("head")[0].appendChild(link)
}

(也可以去 StackOverflow 上看看这篇关于更改网站Favicon的回答)。

你也可以尝试运行一下这段代码,在你的开发工具中复制粘贴这两个函数,然后调用 changeFavicon(“💃")函数. 正确运行代码之后你就可以看到这个图标变成这个跳舞的小图标。

再回到我们这个时间的项目上,如果我们想要在对应的时间里显示正确的时间图标,就需要根据当前时间来确定。例如,如果是10:00,就要显示🕙。如果是4:30,就要显示🕟。并不是每分钟都需要显示图标,在一定的时间范围内显示合适的图标就行。例如,9:45到10:14之间可以显示10:00的图标;10:15到10:44之前可以显示10:30的图标,等等。

可以用下面这个函数来实现:

const currentEmoji = () => {
  // Add 15 minutes and round down to closest half hour
  const time = new Date(Date.now() + 15 * 60 * 1000)

  const hours = time.getHours() % 12
  const minutes = time.getMinutes() < 30 ? 0 : 30

  return {
    "0.0""🕛",
    "0.30""🕧",
    "1.0""🕐",
    "1.30""🕜",
    "2.0""🕑",
    "2.30""🕝",
    "3.0""🕒",
    "3.30""🕞",
    "4.0""🕓",
    "4.30""🕟",
    "5.0""🕔",
    "5.30""🕠",
    "6.0""🕕",
    "6.30""🕡",
    "7.0""🕖",
    "7.30""🕢",
    "8.0""🕗",
    "8.30""🕣",
    "9.0""🕘",
    "9.30""🕤",
    "10.0""🕙",
    "10.30""🕥",
    "11.0""🕚",
    "11.30""🕦",
  }[`${hours}.${minutes}`]
}`enter code here`

现在我们只需要每隔一分钟调用一次 changeFavicon(currentEmoji()),如果要用 JavaScript 来实现的话,定时器 setInterval 就可以解决:

// One minute
const delay = 60 * 1000

// Change the favicon when the page gets loaded...
const emoji = currentEmoji()
changeFavicon(emoji)

// ... and update it every minute
setInterval(() => {
  const emoji = currentEmoji()
  changeFavicon(emoji)
}, delay)

React部分

因为我的博客是基于 Gatsby 的,所以我也希望能在React中去使用这些代码,并尽量减少改动。但因为在React Hooks中setInterval会出现一些问题,而我们又需要每分钟去调用一次,那么该如何去解决呢?

可以先去了解一下Dan Abramov并看看他的这篇关于在React Hooks中声明setInterval的文章。Dan Abramov是一个很棒的博客作者,他习惯用简单清晰的方式去解释复杂的事情,如果你想要更好的理解React Hooks的话,强烈建议你去学习一下这篇文章,不一定要了解它的所有内容——因为钩子函数的优点之一就是,即使你不完全掌握它的底层原理,也可以去实现想要的功能。但重要的是要知道如何使用。下面的代码就简单演示了该如何使用:

import { useEffect } from "react"
import useInterval from "./useInterval"

const delay = 60 * 1000

const useTimeFavicon = () => {
  // Change the favicon when the component gets mounted...
  useEffect(() => {
    const emoji = currentEmoji()
    changeFavicon(emoji)
  }, [])

  // ... and update it every minute
  useInterval(() => {
    const emoji = currentEmoji()
    changeFavicon(emoji)
  }, delay)
}

最后,只需调用 useTimeFavicon() 就可以了,如果想要看它是如何运行的,这是一个已部署好的自动更改时间favicon的项目,可以随着时间的变化观察它的favicon变化,需要进一步了解的话可以看一下它的项目代码。


总结

我们将这三个不同的代码结合起来就能实现我们想要的结果。古罗马人讲,分而治之。如果你把任务看作一个整体,你可能就会有这样的顾虑:“怎样才能在我的React开发的网站中去用合适的favicon显示当前的时间并能实时更新”?完全做好并完善这些问题的细节并不是一件容易的事。

但好在于你不需要同时处理这些问题:把一个问题分成多个子问题会更有效,假如其中任何一个问题已经被其他人解决了,那就会更好的提高效率。

听起来我们好像只是单纯的在做网站开发?但其实重点是我们要知道只要明智合理的运用别人的优秀代码是没有错的,对我们的学习是有帮助的。正如人们所说:没有必要重新发明轮子。所以不管是显示通知,时间更新还是你能想到的其他问题,我们所学到的这些对我们去开发网站都是有提升的。



- EOF -

推荐阅读  点击标题可跳转

1、使用顶层 await 简化 JS 代码

2、2020年,在美国的前端工程师拿多少薪资?

3、从 0 到 1 讲解如何从前后端有效防范点击劫持攻击


觉得本文对你有帮助?请分享给更多人

关注「大前端技术之路」加星标,提升前端技能


点赞和在看就是最大的支持❤️

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存